<script setup lang="ts">
import { ref, shallowRef, watch, onMounted, type ComponentPublicInstance } from 'vue'
import { ScrollView, Pagination } from '@/widgets'
import { type Entity, getEntity, getEntityList } from '../base'
import { getTableDefinition, type EntityTableCellValue, type EntityFilterInstance } from './base'
import { selectMapItem } from '@/map-item'
type Props = {
  type: string
  data?: (type: string) => Entity[]
  selectMode?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  selectMode: false,
  data: (type: string) => getEntityList(type)
})

const emits = defineEmits<{
  (e: 'select', id: string | null): void
}>()

function onSelectedBtn() {
  const id = selected.value
  if (id) {
    emits('select', id)
  }
}

function onCancelBtn() {
  emits('select', null)
}

const def = getTableDefinition(props.type)
let tableWidth = 0
for (const col of def.columns) {
  tableWidth += col.width + 3
}
const lst = props.data(props.type)
let contentData: Entity[] = []

type TableEntry = {
  id: string
  cells: EntityTableCellValue[]
}

function toTableEntry(e: Entity): TableEntry {
  return { id: e.id, cells: def.columns.map((c) => c.cell(e)) }
}

const pageContent = shallowRef<TableEntry[]>([])
const pageEntryCount = 20
const pageIdx = ref(-1)
const pageTotalCount = ref(Math.ceil(contentData.length / pageEntryCount))
const selected = ref<string | null>(null)

let lastClickTime = 0

function select(id: string) {
  const t0 = lastClickTime
  lastClickTime = Date.now()
  if (selected.value === id) {
    if (!props.selectMode) {
      if (lastClickTime - t0 < 220 && def.onDClick) {
        def.onDClick(id)
      }
    }
    return
  }
  selected.value = id
  if (!props.selectMode) {
    const e = getEntity(props.type, id)
    if (e) {
      selectMapItem(`Entity:${props.type}`, e, true)
    }
  }
}

function updatePageContent() {
  const start = pageIdx.value * pageEntryCount
  const end = start + pageEntryCount
  pageContent.value = contentData.slice(start, end).map(toTableEntry)
}

function updateContentData(dat: Entity[]) {
  if (contentData === dat) {
    return
  }
  contentData = dat
  if (pageIdx.value === 0) {
    updatePageContent()
  } else {
    pageIdx.value = 0
  }
  pageTotalCount.value = Math.ceil(contentData.length / pageEntryCount)
  selected.value = null
}

const filter = shallowRef<ComponentPublicInstance>()

function filerData() {
  const f = filter.value as unknown as EntityFilterInstance<Entity>
  updateContentData(f.filter(lst))
}

watch(pageIdx, updatePageContent)

onMounted(() => {
  updateContentData(lst)
})
</script>
<template>
  <div class="entity-table-view">
    <div class="pane-block">
      <div class="row">
        <component ref="filter" :is="def.filter" class="col" />
        <button style="margin-left: 1em" class="button is-primary" @click="filerData">搜索</button>
      </div>
      <ScrollView>
        <table :style="{ width: tableWidth + 'px' }">
          <thead>
            <th v-for="col in def.columns" :style="{ width: `${col.width}px` }">
              {{ col.name }}
            </th>
          </thead>
          <tbody>
            <tr
              v-for="row in pageContent"
              :key="row.id"
              :class="{ 'is-active': selected === row.id }"
              @click="select(row.id)"
            >
              <td v-for="cell in row.cells">{{ cell }}</td>
            </tr>
          </tbody>
        </table>
      </ScrollView>
    </div>
    <div class="pane-footer is-space">
      <Pagination :page-count="pageTotalCount" v-model:current-page="pageIdx" />
      <div class="pane-tool" v-if="selectMode">
        <button class="button" @click="onCancelBtn">取消</button>
        <button class="button is-primary" @click="onSelectedBtn">确定</button>
      </div>
    </div>
  </div>
</template>
<style lang="scss">
@import '@/widgets/var';
.entity-table-view {
  .pane-block {
    padding-bottom: 0;
  }
  .scroll-view {
    min-width: 25em;
    max-width: 45em;
    min-height: 10em;
  }
  table {
    table-layout: fixed;
    word-break: break-all;
    border-collapse: collapse;
    tbody tr:hover {
      background-color: $grey-lightest;
    }

    th,
    td {
      font-size: 1rem;
      height: 1.5em;
      padding: 0.25em 0.5em;
      border: 1px solid #ccc;
      text-overflow: ellipsis;
      white-space: nowrap;
      overflow: hidden;
      word-break: break-word;
    }
    tr.is-active {
      background-color: $primary;
      color: $primary-invert;
      td {
        border-color: $primary;
      }
      &:hover {
        background-color: $primary;
      }
    }
  }
  .pagination {
    margin-bottom: 0;
  }
}
</style>
